package com.quan.pm.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.javafaker.Faker;
import com.quan.commons.utils.NumberUtils;
import com.quan.commons.utils.PageUtils;
import com.quan.hr.entity.HrDept;
import com.quan.hr.entity.HrEmployee;
import com.quan.hr.entity.HrPost;
import com.quan.hr.service.HrCalendarService;
import com.quan.hr.service.HrDeptService;
import com.quan.hr.service.HrEmployeeService;
import com.quan.hr.service.HrPostService;
import com.quan.pm.commons.vo.JDLVo;
import com.quan.pm.service.JDLService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 稼动率计算
 */
@Slf4j
@Service
public class JDLServiceImpl implements JDLService {

    @Autowired
    private HrEmployeeService employeeService;

    @Autowired
    private HrPostService postService;

    @Autowired
    private HrDeptService departService;

    @Autowired
    private HrCalendarService calendarService;

    @Override
    public PageUtils queryPage(PageUtils pageUtils, JDLVo vo) {

        final LambdaQueryWrapper<HrEmployee> wrapper = new QueryWrapper<HrEmployee>().lambda();
        if (StringUtils.isNotBlank(vo.getKeyword())) {
            wrapper.and(w -> {
                w.like(HrEmployee:: getWorkNo, vo.getKeyword()).or().like(HrEmployee:: getName, vo.getKeyword());
            });
        }
        if(null != vo.getDeptId()) {
            wrapper.eq(HrEmployee::getDeptId, vo.getDeptId());
        }
        // 按年份查询
        wrapper.and(w -> {
            Integer year = null != vo.getYear() ? vo.getYear() : LocalDate.now().getYear();
            w.apply("date_format(join_date, '%Y') <= {0}", year).isNull(HrEmployee:: getQuitDate)
            .or().apply("date_format(join_date, '%Y') <= {0}", year).apply("date_format(quit_date, '%Y') >= {0}", year);
        });

        // 查询字段
        wrapper.select(
                HrEmployee::getId,
                HrEmployee::getDeptId,
                HrEmployee::getPostId,
                HrEmployee::getWorkNo,
                HrEmployee::getName,
                HrEmployee::getStatus,
                HrEmployee::getJoinDate,
                HrEmployee::getQuitDate
        );

        // 查询员工
        final IPage<HrEmployee> page = this.employeeService.selectPage(pageUtils, wrapper);

        // 获取指定年份的每月的工作天数（去除周末、节假日，+调休）
        final Map<Integer, Long> workingCountMap = this.calendarService.getYearCalendarWorkingCount(vo.getYear());
        // 总工作天数
        final IntSummaryStatistics totalWorkingDay = workingCountMap.keySet().stream().map(key -> workingCountMap.get(key)).collect(Collectors.summarizingInt(Long::intValue));

        PageUtils ps = new PageUtils(page);

        final List<HrEmployee> records = page.getRecords();
        final List<JDLVo> collect = records.stream().map((item) -> {
            JDLVo bean = new JDLVo();
            BeanUtils.copyProperties(item, bean);
            bean.setEmpName(item.getName());


            // 部门
            if(null != item.getDeptId()){
                final HrDept dept = this.departService.getOne(new LambdaQueryWrapper<HrDept>().eq(HrDept:: getId, item.getDeptId()).select(HrDept::getId, HrDept::getName));
                if(null != dept){
                    bean.setDeptName(dept.getName());
                }
            }

            // 职务
            if(null != item.getPostId()){
                final HrPost post = this.postService.getOne(new LambdaQueryWrapper<HrPost>().eq(HrPost:: getId, item.getPostId()).select(HrPost::getId, HrPost::getName));
                if(null != post) {
                    bean.setPostName(post.getName());
                }
            }

            // 填充每月工作天数
            this.setWorkingDayByMonth(bean, workingCountMap);

            // 填充员工每月稼动率
            this.setJdlByMonth(bean);

            // 填充每个员工的年度稼动率
            this.setEmpYearJDLByMonth(bean);

            // 设置每个员工总的工作天数
            bean.setTotalWorkingDay(totalWorkingDay.getSum());

            return bean;
        }).sorted(Comparator.comparing(JDLVo::getStatus)).collect(Collectors.toList());

        ps.setRecords(collect);

        return ps;
    }

    /**
     * 填充每个员工的年度稼动率
     * @param bean
     */
    private void setEmpYearJDLByMonth(JDLVo bean) {
        try {
            Map<String, String> properties = org.apache.commons.beanutils.BeanUtils.describe(bean);
            List<String> keys = new ArrayList<>(properties.keySet());

            Float sums = 0f;
            for (int i = 1; i <= 12 ; i++) {
                final String value = org.apache.commons.beanutils.BeanUtils.getProperty(bean, "jdlm" + 1);
                sums += Float.parseFloat(value);
            }

            bean.setSumsYearJdl(sums.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 设置每个员工的每月稼动率
     * @param bean
     */
    private void setJdlByMonth(JDLVo bean) {
        // TODO
        try {
            for (int i = 1; i <= 12 ; i++) {
                org.apache.commons.beanutils.BeanUtils.setProperty(bean, "jdlm"+i, NumberUtils.numberFormat(new Faker(Locale.CHINA).random().nextDouble()+"", 2, true));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 设置每个员工的每月工作天数
     * @param bean
     * @param workingCountMap
     */
    private void setWorkingDayByMonth(JDLVo bean, Map<Integer, Long> workingCountMap) {
        try {
            for (Integer month : workingCountMap.keySet()) {
                org.apache.commons.beanutils.BeanUtils.setProperty(bean, "wm"+month, workingCountMap.get(month));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
